home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume11 / mush5.7 / part06 < prev    next >
Encoding:
Internet Message Format  |  1987-09-17  |  54.2 KB

  1. Subject:  v11i056:  Mail user's shell, Part06/12
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: island!argv@Sun.COM (Dan Heller)
  7. Posting-number: Volume 11, Issue 56
  8. Archive-name: mush5.7/Part06
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 6 (of 12)."
  17. # Contents:  curses.c msgs.c mush.h
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'curses.c' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'curses.c'\"
  21. else
  22. echo shar: Extracting \"'curses.c'\" \(17549 characters\)
  23. sed "s/^X//" >'curses.c' <<'END_OF_FILE'
  24. X/* @(#)curses.c    (c) copyright 3/18/87 (Dan Heller) */
  25. X
  26. X/* curses.c -- routine to deal with the curses interface */
  27. X#ifdef CURSES
  28. X
  29. X#include "mush.h"
  30. X#include "bindings.h"
  31. X
  32. Xcurses_init(argc, argv)
  33. Xregister char **argv;
  34. X{
  35. X    char buf[80];
  36. X    extern char *UP, ttytype[];
  37. X
  38. X    if (argv && *++argv && !strcmp(*argv, "-?"))
  39. X    return help(0, "curses", cmd_help);
  40. X    if (iscurses) {
  41. X    print("You can't run curses from the curses mode (silly).");
  42. X    return -1;
  43. X    }
  44. X    if (ison(glob_flags, IS_GETTING)) {
  45. X    print("Finish your letter first.\n");
  46. X    return -1;
  47. X    }
  48. X#ifdef SUNTOOL
  49. X    if (istool) {
  50. X    print("My, aren't we the adventuresome type!");
  51. X    timerclear(&(mail_timer.it_interval));
  52. X    timerclear(&(mail_timer.it_value));
  53. X    tool_destroy(tool), istool = FALSE;
  54. X    curses_init(0, 0);
  55. X    do_loop(); /* doesn't return */
  56. X    }
  57. X#endif SUNTOOL
  58. X
  59. X    /* you can not start curses in no echo mode.. must be in normal mode */
  60. X    echo(), nocrmode();
  61. X    (void) initscr();
  62. X#ifdef SIGCONT
  63. X    /* initscr will play with signals -- make sure they're set right. */
  64. X    (void) signal(SIGTSTP, stop_start);
  65. X    (void) signal(SIGCONT, stop_start);
  66. X#endif SIGCONT
  67. X    if (!UP || !*UP) {
  68. X    print("Terminal type %s can not use the curses interface.\n", ttytype);
  69. X    return -1;
  70. X    }
  71. X    iscurses = TRUE;
  72. X    noecho(), crmode(); /* reset tty state -- do not use "echo_on/off()" */
  73. X    scrollok(stdscr, TRUE);
  74. X    /* if the user hasn't set his screen explicitely, set it for him */
  75. X    if (!do_set(set_options, "screen"))
  76. X    switch (_tty.sg_ospeed) {
  77. X        case B300 : screen = min(LINES-2, 7);
  78. X        when B1200 : screen = min(LINES-2, 14);
  79. X        when B2400 : screen = min(LINES-2, 22);
  80. X        otherwise : screen = LINES-2;
  81. X    }
  82. X    else
  83. X    screen = min(screen, LINES-2);
  84. X    crt = LINES;
  85. X    if (argc)
  86. X    (void) cmd_line(sprintf(buf, "headers %d", current_msg+1), msg_list);
  87. X    if (!do_set(set_options, "no_reverse"))
  88. X    turnon(glob_flags, REV_VIDEO);
  89. X    turnoff(glob_flags, CONT_PRNT);
  90. X    return -1; /* doesn't affect messages */
  91. X}
  92. X
  93. X/*
  94. X * get input in cbreak mode and execute the appropriate command.
  95. X * when the command is done (usually), the user is prompted to
  96. X * hit any key to continue. At this point, the user may enter a
  97. X * new command so no screen refreshing needds to be done. This
  98. X * new command is returned to caller and may be passed back.
  99. X *
  100. X * The variable "cntd_cmd" (continued command) is set to true if
  101. X * this routine is called with the passed parameter (c) > 0. If
  102. X * so, then the character passed is the character input by the
  103. X * user at the last "hit return" prompt indicating that he wants
  104. X * to execute a new command and not draw the screen.
  105. X *
  106. X * cntd_cmd is also set to true if the command that the user invokes
  107. X * causes any sort of output that requires a screen refresh.  The
  108. X * variable redo is set to 1 if the header page not only requires
  109. X * redrawing, but updating ... (new call to do_hdrs)
  110. X *
  111. X * calls that say: print("%s", compose_hdr(current_msg)) are constructed
  112. X * that way cuz if the header has a `%' in it, then print will try to
  113. X * expand it.
  114. X */
  115. Xcurses_command(c)
  116. Xregister int c;
  117. X{
  118. X    char     buf[BUFSIZ], file[128], list[128];
  119. X    int     n, cntd_cmd = (c > 0), curlin;
  120. X    static int  redo;  /* set if headers should be redrawn */
  121. X
  122. X    clear_msg_list(msg_list); /* play it safe */
  123. X    if (!cntd_cmd) {
  124. X    (void) check_new_mail();
  125. X    curlin = max(1, current_msg - n_array[0] + 1);
  126. X    (void) strncpy(buf, stdscr->_y[curlin], COLS-1);
  127. X    buf[COLS-1] = 0; /* strncpy does not null terminate */
  128. X    if (ison(glob_flags, REV_VIDEO) && msg_cnt)
  129. X        STANDOUT(curlin, 0, buf);
  130. X    mail_status(0);
  131. X    move(curlin, 0), refresh();
  132. X    /* reprint to remove reverse video from current line (don't refresh) */
  133. X    if (ison(glob_flags, REV_VIDEO))
  134. X        mvaddstr(curlin, 0, buf);
  135. X    c = getcmd(); /* get input AFTER line redrawn without reverse video */
  136. X    }
  137. X    buf[0] = list[0] = file[0] = '\0';
  138. X
  139. X    /* goto a specific line number */
  140. X    if (c == C_GOTO_MSG) {
  141. X    c = C_NULL;
  142. X    if (msg_cnt <= 1)
  143. X        print("Not enough messages.");
  144. X    else if (curses_msg_list(strcpy(buf, "goto msg: "), list, msg_list)) {
  145. X        for (n = 0; !msg_bit(msg_list, n); n++)
  146. X        ;
  147. X        if ((current_msg = n) < n_array[0] || n > n_array[screen-1])
  148. X        redo = 1;
  149. X    }
  150. X    if (cntd_cmd && msg_cnt)
  151. X        print("%s", compose_hdr(current_msg));
  152. X    if (cntd_cmd)
  153. X        putchar('\n');
  154. X    } else if (c == C_WRITE_LIST || c == C_SAVE_LIST || c == C_COPY_LIST
  155. X                   || c == C_DELETE_LIST || c == C_UNDEL_LIST) {
  156. X    
  157. X    if (msg_cnt <= 1)
  158. X        print("Not enough messages."), c = C_NULL;
  159. X    else if (!curses_msg_list(sprintf(buf, "%s msg list: ",
  160. X        (c == C_WRITE_LIST)? "write" : (c == C_SAVE_LIST)?  "save" :
  161. X        (c == C_DELETE_LIST)? "delete" : "undelete"), list, msg_list))
  162. X        c = C_NULL;
  163. X    if (cntd_cmd)
  164. X        putchar('\n');
  165. X    }
  166. X
  167. X    /* first do non-mail command stype stuff */
  168. X    switch (c) {
  169. X    case C_NULL : ;
  170. X
  171. X    /* screen optimization stuff */
  172. X    when C_REVERSE :
  173. X        if (ison(glob_flags, REV_VIDEO))
  174. X        turnoff(glob_flags, REV_VIDEO);
  175. X        else
  176. X        turnon(glob_flags, REV_VIDEO);
  177. X
  178. X    when C_REDRAW : if (!redo) redraw();
  179. X
  180. X    /*
  181. X     * screen movement
  182. X     */
  183. X    when C_NEXT_MSG :
  184. X    /* case 'j' : case 'J' : case '+' : case '\n' : /* next */
  185. X        if (current_msg + 2 > msg_cnt || !cntd_cmd && curlin == screen)
  186. X        bell(); /* reached the end */
  187. X        else {
  188. X        if (++current_msg > n_array[screen-1])
  189. X            redo = 1;
  190. X        if (cntd_cmd)
  191. X            print("%s", compose_hdr(current_msg)), putchar('\n');
  192. X        }
  193. X    when C_PREV_MSG :
  194. X    /* when 'k' : case 'K' : case '-' : case CTRL(k) : /* previous */
  195. X        if (!cntd_cmd && curlin == 1 || current_msg == 0)
  196. X        bell();  /* at the beginning */
  197. X        else {
  198. X        if (--current_msg < n_array[0])
  199. X            redo = 1;
  200. X        if (cntd_cmd)
  201. X            print("%s", compose_hdr(current_msg)), putchar('\n');
  202. X        }
  203. X    when C_FIRST_MSG : case C_LAST_MSG :
  204. X        n = current_msg;
  205. X        if (c == C_FIRST_MSG && (current_msg = 0) < n_array[0] ||
  206. X        c == C_LAST_MSG && (current_msg = msg_cnt-1)> n_array[screen-1])
  207. X        if (!cntd_cmd)
  208. X            (void) cmd_line(sprintf(buf, "headers %d", current_msg+1),
  209. X                 msg_list);
  210. X        else
  211. X            redo = 1;
  212. X        if (cntd_cmd && n != current_msg)
  213. X        print("%s", compose_hdr(current_msg)), putchar('\n');
  214. X    /* top and bottom of headers screen */
  215. X    when C_TOP_PAGE : case C_BOTTOM_PAGE :
  216. X        if (!cntd_cmd)
  217. X        if (c == C_TOP_PAGE)
  218. X            current_msg = n_array[0];
  219. X        else
  220. X            current_msg = min(n_array[screen-1], msg_cnt-1);
  221. X        else
  222. X        bell();
  223. X    when C_NEXT_SCREEN : /* next page */
  224. X        if (msg_cnt > screen) {
  225. X        (void) cmd_line(strcpy(buf, "headers +"), msg_list);
  226. X        current_msg = n_array[0];
  227. X        return redo = 0;
  228. X        } else
  229. X        bell();
  230. X    when C_PREV_SCREEN : /* previous page */
  231. X        if (current_msg > 0 || cntd_cmd)
  232. X        (void) cmd_line(strcpy(buf, "headers -"), msg_list), redo = 0;
  233. X        current_msg = (msg_cnt <= 1)? 0 : n_array[0];
  234. X        return 0;
  235. X        /* break;  (not stated for lint) */
  236. X
  237. X    case C_SHOW_HDR :
  238. X        if (cntd_cmd && msg_cnt)
  239. X        puts(compose_hdr(current_msg));
  240. X
  241. X    /* read from/save to record file (.mushrc) */
  242. X    when C_SOURCE : case C_SAVEOPTS :
  243. X        print("%s filename [default]: ",
  244. X        (c == C_SOURCE)? "source" : "save options to");
  245. X        if (Getstr(file, LINES-40, 0) < 0) {
  246. X        clr_bot_line();
  247. X        return 0;
  248. X        }
  249. X        iscurses = FALSE;
  250. X        turnon(glob_flags, PRE_CURSES);
  251. X        (void) cmd_line(sprintf(buf, "%s %s",
  252. X        (c == C_SOURCE) ? "source" : "saveopts", file), msg_list);
  253. X        iscurses = TRUE;
  254. X        turnoff(glob_flags, PRE_CURSES);
  255. X        cntd_cmd = 1;
  256. X
  257. X    /*
  258. X     * search commands
  259. X     */
  260. X    when C_NEXT_SEARCH : case C_PREV_SEARCH : case C_CONT_SEARCH :
  261. X        if (c != C_CONT_SEARCH)
  262. X        c = search(0 + (c == C_PREV_SEARCH));
  263. X        else
  264. X        c = search(-1);
  265. X        if (cntd_cmd)
  266. X        putchar('\n');
  267. X        if (c == 0)
  268. X        break;
  269. X        if (cntd_cmd)
  270. X        print("%s", compose_hdr(current_msg)), putchar('\n');
  271. X        if (n_array[0] > current_msg || n_array[screen-1] < current_msg) {
  272. X        redo = 1;
  273. X        if (!cntd_cmd)
  274. X            (void) cmd_line(sprintf(buf, "headers %d",
  275. X                        current_msg+1), msg_list);
  276. X        }
  277. X
  278. X    /*
  279. X     * actions on messages
  280. X     */
  281. X    /* delete/undelete */
  282. X    when C_DELETE_MSG : case C_DELETE_LIST :
  283. X    case C_UNDEL_MSG : case C_UNDEL_LIST :
  284. X        if (!msg_cnt) {
  285. X        print("No messages.");
  286. X        if (cntd_cmd)
  287. X            putchar('\n');
  288. X        break;
  289. X        }
  290. X        if (!*list)
  291. X        set_msg_bit(msg_list, current_msg);
  292. X        turnon(glob_flags, DO_UPDATE);
  293. X        for (n = 0; n < msg_cnt; n++)
  294. X        if (msg_bit(msg_list, n)) {
  295. X            if (c == C_DELETE_MSG || c == C_DELETE_LIST)
  296. X            turnon(msg[n].m_flags, DELETE);
  297. X            else
  298. X            turnoff(msg[n].m_flags, DELETE);
  299. X            if (!cntd_cmd && msg_cnt < screen ||
  300. X            !cntd_cmd && n >= n_array[0] && n <= n_array[screen-1])
  301. X            mvaddstr(max(1, n - n_array[0] + 1), 0, compose_hdr(n));
  302. X            else
  303. X            redo = 1;
  304. X        }
  305. X        if (cntd_cmd || *list) {
  306. X        if (cntd_cmd) { /* print(), THEN putchar() -- overwrite line */
  307. X            print("%sdeleted %s",
  308. X            (c == C_DELETE_MSG || c == C_DELETE_LIST)? "":"un", list);
  309. X            putchar('\n');
  310. X        }
  311. X        if (ison(msg[current_msg].m_flags, DELETE))
  312. X            (void) next_msg(FALSE, DELETE);
  313. X        if (do_set(set_options, "autoprint"))
  314. X            return C_DISPLAY_MSG;
  315. X        if (cntd_cmd)
  316. X            puts(compose_hdr(current_msg));
  317. X        }
  318. X
  319. X    /*
  320. X     * write/save messages.  If a list is necessary, the user already
  321. X     * entered it above since he must have used a capital letter. If so,
  322. X     * list will contain good data (already been validated above).
  323. X     * if a list is given, set iscurses to 0 so that print statements
  324. X     * will scroll and the user sees the multiple output. else, one
  325. X     * line can go on the bottom line just fine.
  326. X     */
  327. X    when C_WRITE_MSG : case C_SAVE_MSG : case C_COPY_MSG :
  328. X    case C_WRITE_LIST : case C_SAVE_LIST : case C_COPY_LIST : {
  329. X        register char *p =
  330. X        (c == C_WRITE_MSG || c == C_WRITE_LIST)? "write" :
  331. X        (c == C_SAVE_MSG  || c == C_SAVE_LIST)?  "save"  : "copy";
  332. X        print(sprintf(buf, "filename to %s [mbox]: ", p));
  333. X        if (Getstr(file, COLS-1-strlen(buf), 0) >= 0) {
  334. X        char *argv[3];
  335. X        clr_bot_line();
  336. X        argv[0] = strcpy(buf, p);
  337. X        argv[1] = file;
  338. X        argv[2] = NULL;
  339. X        if (!*list)
  340. X            set_msg_bit(msg_list, current_msg);
  341. X        move(LINES-1, 0), refresh();
  342. X        if (*list)
  343. X            iscurses = FALSE;
  344. X        turnon(glob_flags, IS_PIPE);
  345. X        if (save_msg(2, argv, msg_list) < 0)
  346. X            *list = 0;
  347. X        turnoff(glob_flags, IS_PIPE);
  348. X        if (cntd_cmd)
  349. X            putchar('\n'), puts(compose_hdr(current_msg));
  350. X        if (*list)
  351. X            iscurses = cntd_cmd = redo = TRUE;
  352. X        else if (!cntd_cmd && msg_cnt)
  353. X            mvaddstr(curlin, 0, compose_hdr(current_msg));
  354. X        } else {
  355. X        print("No messages saved.");
  356. X        if (cntd_cmd)
  357. X            putchar('\n');
  358. X        }
  359. X    }
  360. X
  361. X    /* preserve message */
  362. X    when C_PRESERVE :
  363. X        if (!msg_cnt) {
  364. X        print("No messages.");
  365. X        if (cntd_cmd)
  366. X            putchar('\n');
  367. X        break;
  368. X        }
  369. X        if (ison(msg[current_msg].m_flags, PRESERVE))
  370. X        turnoff(msg[current_msg].m_flags, PRESERVE);
  371. X        else
  372. X        turnon(msg[current_msg].m_flags, PRESERVE);
  373. X        if (cntd_cmd) {
  374. X        print("%s", compose_hdr(current_msg)), putchar('\n');
  375. X        redo = 1;
  376. X        } else
  377. X        mvaddstr(curlin, 0, compose_hdr(current_msg));
  378. X
  379. X    /* order messages (sort) and rediesplay the headers */
  380. X    when C_SORT : case C_REV_SORT :
  381. X        (void) strcpy(file, "sort");
  382. X        if (c == C_REV_SORT) {
  383. X        print("Reverse "), turnon(glob_flags, CONT_PRNT);
  384. X        (void) strcat(file, " -");
  385. X        }
  386. X        print("Order messages by [Status, date, subject, author]: ");
  387. X        if ((c = getchar()) == 's' || c == 'S' || c == 'd' || c == 'a') {
  388. X        print("reordering messages...");
  389. X        (void) cmd_line(sprintf(buf, "%s %c", file, c), msg_list);
  390. X        print_more("done.");
  391. X        if (cntd_cmd)
  392. X            putchar('\n'), puts(compose_hdr(current_msg));
  393. X        redo = 1;
  394. X        } else
  395. X        clr_bot_line();
  396. X
  397. X    when C_QUIT_HARD :
  398. X        (void) quit(0, DUBL_NULL);
  399. X        redo = 1; /* new mail must have come in */
  400. X
  401. X    /* quit or update -- vrfy_update (returns 1 if updated) */
  402. X    when C_QUIT : case C_UPDATE :
  403. X        if (!vrfy_update(&cntd_cmd, &redo))
  404. X        if (c == C_UPDATE)
  405. X            break;
  406. X        else
  407. X            turnoff(glob_flags, DO_UPDATE);
  408. X        if (c == C_QUIT) {
  409. X        putchar('\n');
  410. X        cleanup(0);
  411. X        redo = 1;
  412. X        }
  413. X
  414. X    when C_EXIT : case C_EXIT_HARD :
  415. X        clr_bot_line();
  416. X        iscurses = FALSE;
  417. X        if (c != C_EXIT && c != C_EXIT_HARD)
  418. X        putchar('\n');
  419. X        cleanup(0);
  420. X
  421. X    /* change to a new folder */
  422. X    when C_FOLDER :
  423. X        for (;;) {
  424. X        print("New folder (?=list): ");
  425. X        if (Getstr(file, COLS-22, 0) > 0) {
  426. X            if (!strcmp(file, "?")) {
  427. X            clr_bot_line();
  428. X            iscurses = 0;
  429. X            puts("folders in your folder directory:");
  430. X            (void) cmd_line(strcpy(buf, "folders"), msg_list);
  431. X    puts("Precede folder names with a +. `%' to specify system mailbox.");
  432. X            cntd_cmd = iscurses = 1;
  433. X            continue;
  434. X            }
  435. X            clearok(stdscr, FALSE);
  436. X            if (strcmp(file, "-?"))
  437. X            vrfy_update(&cntd_cmd, &redo);
  438. X            move(LINES-1, 0), refresh();
  439. X            if (cmd_line(sprintf(buf, "folder ! -N %s", file),
  440. X                 msg_list) == -1) {
  441. X            /* error message was printed; leave room to read it */
  442. X            putchar('\n');
  443. X            cntd_cmd = 1, redo = 0;
  444. X            } else
  445. X            redo = 1, cntd_cmd = 0;
  446. X            break;
  447. X        } else {
  448. X            print("\"%s\" unchanged.", mailfile);
  449. X            if (cntd_cmd)
  450. X            putchar('\n');
  451. X            break;
  452. X        }
  453. X        }
  454. X
  455. X    /* shell escape */
  456. X    when C_SHELL_ESC :
  457. X        print("Shell command: ");
  458. X        if (Getstr(file, COLS-24, 0) < 0)
  459. X        clr_bot_line();
  460. X        else {
  461. X        putchar('\n');
  462. X        iscurses = FALSE;
  463. X        (void) cmd_line(sprintf(buf, "sh %s", file), msg_list);
  464. X        iscurses = TRUE;
  465. X        cntd_cmd = 1;
  466. X        }
  467. X
  468. X    /* do a line-mode like command */
  469. X    when C_CURSES_ESC :
  470. X        print(":");
  471. X        if (Getstr(buf, COLS-2, 0) < 0)
  472. X        break;
  473. X        putchar('\n');
  474. X        iscurses = FALSE;
  475. X        if (!*buf) {
  476. X        /* return -1 because iscurses = 0 is not enough! */
  477. X        redo = 0;
  478. X        endwin(); /* this turns echoing back on! */
  479. X        echo_off();
  480. X        return -1;
  481. X        }
  482. X        (void) cmd_line(buf, msg_list);
  483. X        /* they may have affected message status or had text output */
  484. X        cntd_cmd = redo = 1;
  485. X        iscurses = TRUE;
  486. X        if (msg_cnt)
  487. X        puts(compose_hdr(current_msg));
  488. X
  489. X    /* send message to printer */
  490. X    when C_PRINT_MSG : lpr(0, DUBL_NULL, msg_list);
  491. X
  492. X    /* cd */
  493. X    when C_CHDIR :
  494. X        print("chdir to [.]: ");
  495. X        if (Getstr(file, COLS-12, 0) < 0)
  496. X        break;
  497. X        clr_bot_line();
  498. X        (void) cmd_line(sprintf(buf, "cd %s", file), msg_list);
  499. X        if (cntd_cmd)
  500. X        putchar('\n');
  501. X
  502. X    /* variable settings */
  503. X    when C_VAR_SET : case C_IGNORE : case C_ALIAS : case C_OWN_HDR :
  504. X        curs_vars(c, &cntd_cmd); /* cntd_cmd is reset if there's output! */
  505. X
  506. X    when C_VERSION :
  507. X        do_version(); /* duh */
  508. X        if (cntd_cmd)
  509. X        putchar('\n');
  510. X
  511. X    when C_MAIL_FLAGS :
  512. X        print("flags [-?]: ");
  513. X        if ((c = Getstr(file, COLS-50, 0)) < 0)
  514. X        break;
  515. X        putchar('\n');
  516. X        if (c == 0)
  517. X        (void) strcpy(file, "-?");
  518. X    /* Fall thru */
  519. X    case C_MAIL :
  520. X        clr_bot_line();
  521. X        iscurses = FALSE;
  522. X        (void) cmd_line(sprintf(buf, "mail %s", file), msg_list);
  523. X        iscurses = TRUE, cntd_cmd = 1;
  524. X        if (msg_cnt)
  525. X        print("%s", compose_hdr(current_msg)), putchar('\n');
  526. X
  527. X    /* reply to mail */
  528. X    when C_REPLY_SENDER : case C_REPLY_ALL : {
  529. X        register char *p = (c == C_REPLY_ALL)? "replyall" : "replysender";
  530. X        clr_bot_line();
  531. X        iscurses = FALSE;
  532. X        (void) cmd_line(sprintf(buf, "%s %d", p, current_msg+1),
  533. X        msg_list);
  534. X        iscurses = TRUE, cntd_cmd = 1;
  535. X        if (msg_cnt)
  536. X        print("%s", compose_hdr(current_msg)), putchar('\n');
  537. X    }
  538. X
  539. X    /* type out a message */
  540. X    when C_DISPLAY_MSG : case C_TOP_MSG : case C_DISPLAY_NEXT :
  541. X        if (!msg_cnt ||
  542. X        c != C_DISPLAY_NEXT && ison(msg[current_msg].m_flags, DELETE)) {
  543. X        if (!msg_cnt)
  544. X            print("No messages.");
  545. X        else
  546. X            print("Message %d deleted; type 'u' to undelete.",
  547. X                      current_msg+1);
  548. X        if (cntd_cmd)
  549. X            putchar('\n');
  550. X        break;
  551. X        }
  552. X        clr_bot_line();
  553. X        iscurses = FALSE;
  554. X        if (cntd_cmd)
  555. X        putchar('\n');
  556. X        if (c == C_DISPLAY_MSG)
  557. X        c = cmd_line(strcpy(buf, "type"), msg_list);
  558. X        else if (c == C_TOP_MSG)
  559. X        c = cmd_line(strcpy(buf, "top"), msg_list);
  560. X        else
  561. X        c = cmd_line(strcpy(buf, "next"), msg_list);
  562. X        if (c > -1)
  563. X        cntd_cmd = redo = 1;
  564. X        iscurses = TRUE;
  565. X        puts(compose_hdr(current_msg));
  566. X
  567. X    /* bind a key or string to a command */
  568. X    when C_BIND :  case C_UNBIND : {
  569. X        char *argv[2];
  570. X        argv[0] = (c == C_BIND) ? "bind" : "unbind";
  571. X        argv[1] = NULL;
  572. X        if (bind_it(0, argv) < -1)
  573. X        cntd_cmd = 1;
  574. X        else if (cntd_cmd) /* if it was already set anyway */
  575. X        putchar('\n');
  576. X    }
  577. X
  578. X    /* help stuff */
  579. X    when C_HELP :
  580. X        (void) c_bind(NULL);
  581. X        cntd_cmd = 1;
  582. X        if (msg_cnt)
  583. X        puts(compose_hdr(current_msg));
  584. X
  585. X    /* now do interactive stuff as if run from the mush shell */
  586. X    otherwise :
  587. X        bell();
  588. X        if (cntd_cmd) {
  589. X        /* use print instead of puts to overwrite hit_return msg */
  590. X        print("unknown command"), putchar('\n');
  591. X        redo = 1;
  592. X        }
  593. X    }
  594. X
  595. X    if (cntd_cmd) {
  596. X    int old_cnt = msg_cnt;
  597. X    if (!(c = hit_return()) && !redo && msg_cnt == old_cnt)
  598. X        redraw();
  599. X    clr_bot_line();
  600. X    if (old_cnt !=  msg_cnt)
  601. X        redo = 1;
  602. X    if (c)
  603. X        return c;
  604. X    }
  605. X    if (redo) {
  606. X    n = current_msg;
  607. X    clear();
  608. X    if (msg_cnt < screen || n_array[0] < n && n < n_array[screen-1])
  609. X        (void) do_hdrs(0, DUBL_NULL, NULL);
  610. X    else
  611. X        (void) cmd_line(sprintf(buf, "headers %d", n+1), msg_list);
  612. X    redo = 0;
  613. X    }
  614. X    return 0;
  615. X}
  616. X
  617. Xvrfy_update(cntd_cmd, redo)
  618. Xint *cntd_cmd, *redo;
  619. X{
  620. X    char buf[16];
  621. X    int c;
  622. X
  623. X    /* update current folder */
  624. X    if (ison(glob_flags, DO_UPDATE)) {
  625. X    print("Update %s [y]? ", mailfile);
  626. X    if ((c = getchar()) == 'n' || c == 'N' || c == 7 || c == 127 || c == 4){
  627. X        print("%s unmodified.", mailfile);
  628. X        if (*cntd_cmd)
  629. X        putchar('\n');
  630. X        return 0;
  631. X    }
  632. X    (void) cmd_line(strcpy(buf, "update"), msg_list);
  633. X    if (*cntd_cmd)
  634. X        *redo = 1, *cntd_cmd = 0;
  635. X    }
  636. X    turnoff(glob_flags, DO_UPDATE);
  637. X    return 1; /* make sure bottom line is clear and no reverse video */
  638. X}
  639. X#endif CURSES
  640. END_OF_FILE
  641. if test 17549 -ne `wc -c <'curses.c'`; then
  642.     echo shar: \"'curses.c'\" unpacked with wrong size!
  643. fi
  644. # end of 'curses.c'
  645. fi
  646. if test -f 'msgs.c' -a "${1}" != "-c" ; then 
  647.   echo shar: Will not clobber existing file \"'msgs.c'\"
  648. else
  649. echo shar: Extracting \"'msgs.c'\" \(16268 characters\)
  650. sed "s/^X//" >'msgs.c' <<'END_OF_FILE'
  651. X/* @(#)msgs.c    (c) copyright 10/18/86 (Dan Heller) */
  652. X
  653. X#include "mush.h"
  654. X#ifdef SYSV
  655. X#include <sys/locking.h>
  656. X#endif SYSV
  657. X
  658. Xvoid
  659. Xdisplay_msg(n, flg)
  660. Xregister int n;
  661. Xlong flg;
  662. X{
  663. X    register FILE *pp;
  664. X
  665. X    if (ison(msg[n].m_flags, DELETE)) {
  666. X    print("Message %d deleted; ", n+1);
  667. X    if (istool)
  668. X        print_more("Select UNDELETE to read.");
  669. X    else if (iscurses)
  670. X        print_more("Type 'u' to undelete.");
  671. X    else
  672. X        print("Type 'undelete %d' to undelete\n", n+1);
  673. X    return;
  674. X    }
  675. X    set_isread(n);
  676. X    if (ison(flg, TOP)) {
  677. X    turnon(flg, NO_HEADER);
  678. X    print("Top of "), turnon(glob_flags, CONT_PRNT);
  679. X    }
  680. X
  681. X    if (!istool && isoff(flg, NO_PAGE) &&
  682. X        crt < msg[n].m_lines && isoff(flg, TOP)) {
  683. X    turnon(glob_flags, IGN_SIGS);
  684. X    echo_on();
  685. X    if (!(pp = popen(pager, "w")))
  686. X        error(pager);
  687. X    else {
  688. X        fprintf(pp, "Message #%d (%d lines)\n", n+1, msg[n].m_lines);
  689. X        (void) copy_msg(n, pp, flg);
  690. X        (void) pclose(pp);
  691. X    }
  692. X    echo_off();
  693. X    turnoff(glob_flags, IGN_SIGS);
  694. X    } else {
  695. X    print("Message #%d (%d lines)\n", n+1, msg[n].m_lines);
  696. X    (void) copy_msg(n, stdout, flg);
  697. X    }
  698. X}
  699. X
  700. X/*
  701. X * copy message 'n' to file "fp" according to various flag arguments
  702. X * return number of lines copied or -1 if system error on fputs.
  703. X */
  704. Xcopy_msg(n, fp, flags)
  705. Xregister int n;
  706. Xlong flags;
  707. Xregister FILE *fp;
  708. X{
  709. X    register int  ignoring = 0, lines = 0;
  710. X    register char *indent_str;
  711. X    int  on_hdr = 1, top, squeeze = FALSE;
  712. X    char       line[BUFSIZ];
  713. X
  714. X    still_more = 0;
  715. X    if (ison(flags, TOP)) {
  716. X    register char *p = do_set(set_options, "toplines");
  717. X    top = (p)? atoi(p) : crt;
  718. X    }
  719. X    if (do_set(set_options, "alwaysignore"))
  720. X    turnoff(flags, NO_IGNORE);
  721. X    if (isoff(flags, NO_IGNORE) && do_set(set_options, "squeeze"))
  722. X    squeeze = TRUE;
  723. X
  724. X#ifdef SUNTOOL
  725. X    if (istool && fp == stdout) {
  726. X    register int x = (msg[n].m_lines + 2) * l_height(curfont);
  727. X    if (x > 32765) { /* to overcome a bug in pixrects that sun won't fix */
  728. X        print("message too big to display using this font");
  729. X        return 0;
  730. X    }
  731. X    if (x < msg_rect.r_height) /* make it at least as big as the window */
  732. X        x = msg_rect.r_height;
  733. X    do_clear();
  734. X    lock_cursors();
  735. X    if (!(msg_pix = mem_create(msg_rect.r_width, x, 1))) {
  736. X        error("mem_create");
  737. X        return 0;
  738. X    }
  739. X    pr_rop(msg_pix, 0,0, msg_rect.r_width-1, x-1, PIX_CLR, 0,0,0);
  740. X    on_hdr = 1;
  741. X    }
  742. X#endif SUNTOOL
  743. X    if (ison(flags, INDENT) &&
  744. X       (!(indent_str = do_set(set_options, "indent_str")) ||
  745. X    !strcmp(indent_str, "indent_str")))
  746. X    indent_str = DEF_INDENT_STR;
  747. X    (void) fseek(tmpf, msg[n].m_offset, L_SET);
  748. X    while (still_more < msg[n].m_size && fgets(line, BUFSIZ, tmpf)) {
  749. X    still_more += strlen(line);
  750. X
  751. X    /*
  752. X     * If squeeze is one, all blanks lines squeeze down to one blank line.
  753. X     * If squeeze is two, squeezing is in progress. Otherwise, wait for \n.
  754. X     */
  755. X    if (*line == '\n') {
  756. X        if (on_hdr)    /* blank line -- end of header */
  757. X        turnoff(flags, NO_HEADER), on_hdr = 0;
  758. X        if (squeeze > 1)
  759. X        continue;
  760. X        else if (squeeze)
  761. X        squeeze = 2;
  762. X    } else if (squeeze > 1)
  763. X        squeeze = 1;
  764. X
  765. X    if (ison(flags, UPDATE_STATUS))
  766. X        if (!strncmp(line, "Status:", 7))
  767. X        continue; /* ignore this and other "Status" lines */
  768. X        else if (!on_hdr) {
  769. X        /* preserve NEW/UNREAD status on preserved messages */
  770. X        if (isoff(msg[n].m_flags, PRESERVE)) {
  771. X            (void) strcpy(line, "Status: O");
  772. X            if (isoff(msg[n].m_flags, UNREAD))
  773. X            (void) strcat(line, "R");
  774. X            (void) strcat(line, "\n");
  775. X            fputs(line, fp);
  776. X            (void) strcpy(line, "\n");
  777. X        }
  778. X        turnoff(flags, UPDATE_STATUS);
  779. X        }
  780. X    if (on_hdr && isoff(flags, NO_IGNORE)) {
  781. X        register char *p = any(line, " \t:");
  782. X        if (!p)
  783. X        ignoring = 0, on_hdr = 0;
  784. X        else if (ignoring)
  785. X        if (*p != ':') {
  786. X            Debug("Ignoring: %s", line);
  787. X            continue;
  788. X        }
  789. X        else
  790. X            ignoring = 0;
  791. X        if (p && *p == ':') {
  792. X        register struct options *opts;
  793. X        *p = 0;
  794. X        ignoring = 0;
  795. X        for (opts = ignore_hdr; opts; opts = opts->next)
  796. X            if (!lcase_strcmp(opts->option, line)) {
  797. X            ignoring = 1;
  798. X            break;
  799. X            }
  800. X        *p = ':';
  801. X        if (ignoring) {
  802. X            Debug("Ignoring: %s", line);
  803. X            continue;
  804. X        }
  805. X        }
  806. X    }
  807. X    if (!on_hdr && ison(flags, TOP) && !--top)
  808. X        break;
  809. X    if (isoff(flags, NO_HEADER)) {
  810. X        /* note that function returns the number of lines */
  811. X        lines++;
  812. X#ifdef SUNTOOL
  813. X        if (istool && fp == stdout) {
  814. X        Addstr(line);
  815. X        continue;
  816. X        }
  817. X#endif SUNTOOL
  818. X        if (ison(flags, INDENT))
  819. X        fputs(indent_str, fp);
  820. X        (void) fputs(line, fp);
  821. X        if (errno == ENOSPC)
  822. X        return -1;
  823. X    }
  824. X    }
  825. X#ifdef SUNTOOL
  826. X    if (istool && fp == stdout) {
  827. X    unlock_cursors();
  828. X    txt.y = still_more = msg_rect.r_height;
  829. X    scroll_win(0);  /* causes a display */
  830. X    }
  831. X#endif SUNTOOL
  832. X    return lines;
  833. X}
  834. X
  835. X/* get mail from whatever the mailfile points to. open a tempfile for
  836. X * appending, then close it and reopen it for read-only.  some systems
  837. X * have flakey read/write access.
  838. X */
  839. Xvoid
  840. Xgetmail()
  841. X{
  842. X    register FILE    *mail_fp;
  843. X    int     lines = 0, get_status = 1;
  844. X    long     ftell(), bytes;
  845. X    char    line[BUFSIZ];
  846. X
  847. X    if (!(mail_fp = fopen(mailfile, "r"))) {
  848. X    error("Cannot open %s", mailfile);
  849. X    return;
  850. X    }
  851. X    /*
  852. X     * since this file is usually open for read-only, close it and then
  853. X     * reopen it for appending.  This is done to compensate for errors
  854. X     * in XENIX and to play it safe with non-essentially writable files.
  855. X     * see more notes below (end of proc).
  856. X     */
  857. X    (void) fclose(tmpf);
  858. X    {
  859. X    int    omask = umask(077);
  860. X    tmpf = fopen(tempfile, "a");
  861. X    (void) umask(omask);
  862. X    if (!tmpf) {
  863. X        error("can't open %s for appending", tempfile);
  864. X        (void) fclose(mail_fp);
  865. X        return;
  866. X    }
  867. X    }
  868. X#ifdef SYSV
  869. X    (void) locking(fileno(mail_fp), LK_LOCK,  0);
  870. X#else
  871. X#ifdef BSD
  872. X    if (flock(fileno(mail_fp), LOCK_SH))  /* if file is locked, flock waits */
  873. X    error("WARNING: could not lock %s", mailfile);
  874. X#endif BSD
  875. X#endif SYSV
  876. X
  877. X    (void) fseek(mail_fp, ftell(tmpf), 0);
  878. X
  879. X    while (fgets(line, BUFSIZ, mail_fp) != NULL) {
  880. X    if (!strncmp(line, "From ", 5)) {
  881. X        if (msg_cnt == MAXMSGS-1) {
  882. X        print("WARNING: exceeded %d messages.\n", MAXMSGS);
  883. X        print("You should split \"%s\" into smaller files.\n",mailfile);
  884. X        /* make sure that tempfile isn't removed!! */
  885. X        turnon(glob_flags, IGN_SIGS);
  886. X        cleanup(0); /* probably a more elegant way to exit, but... */
  887. X        }
  888. X        bytes = ftell(tmpf);
  889. X        /* finish up message structure from previous message.
  890. X         * if this is incorporating new mail, check "lines" to
  891. X         * see if previous message has already been set!
  892. X         */
  893. X        if (msg_cnt && lines) {
  894. X        msg[msg_cnt-1].m_size = bytes - msg[msg_cnt-1].m_offset;
  895. X        msg[msg_cnt-1].m_lines = lines;
  896. X        }
  897. X        msg[msg_cnt].m_offset = bytes;
  898. X        msg[msg_cnt].m_flags = lines = 0;
  899. X        turnon(msg[msg_cnt].m_flags, UNREAD); /* initialize */
  900. X
  901. X        fputs(line, tmpf);
  902. X        if (errno == ENOSPC)
  903. X        fs_error();
  904. X
  905. X        /* we've read the "From " line, now read the rest of
  906. X         * the message headers till we get to a blank line.
  907. X         */
  908. X        while (fgets(line, BUFSIZ, mail_fp) && (*line != '\n')) {
  909. X        register char *p = line;
  910. X        if (get_status && !(get_status = strncmp(p, "Status:", 7))) {
  911. X            turnon(msg[msg_cnt].m_flags, OLD);
  912. X            for (p += 8 ; *p != '\n'; p++)
  913. X            switch(*p) {
  914. X                case 'R': turnoff(msg[msg_cnt].m_flags, UNREAD);
  915. X            }
  916. X        }
  917. X        fputs(line, tmpf), lines++;
  918. X        if (errno == ENOSPC)
  919. X            fs_error();
  920. X        }
  921. X        msg_cnt++, get_status = 1;
  922. X    }
  923. X    fputs(line, tmpf), lines++;
  924. X    if (errno == ENOSPC)
  925. X        fs_error();
  926. X    }
  927. X    /* msg_cnt may be 0 if there is an error with the format of mailfile */
  928. X    if (msg_cnt) {
  929. X    msg[msg_cnt-1].m_size = ftell(tmpf) - msg[msg_cnt-1].m_offset;
  930. X    msg[msg_cnt-1].m_lines = lines;
  931. X    }
  932. X#ifdef SYSV
  933. X    locking(fileno(mail_fp), LK_UNLCK, 0);
  934. X#endif /* SYSV */
  935. X    fclose(mail_fp);            /* implicit unlock */
  936. X    /* I've had problems with sys-v opening a file for read/write. I'd
  937. X     * try fgets after a seek to an arbitrary place and get NULL. "w+"
  938. X     * could be broken (XENIX), so play it safe anyway.
  939. X     */
  940. X    fclose(tmpf);
  941. X    if (!(tmpf = fopen(tempfile, "r")))
  942. X    error("can't open %s for reading", tempfile);
  943. X}
  944. X
  945. Xfs_error()
  946. X{
  947. X    error("WARNING: can't write to \"%s\"", tempfile);
  948. X    print("Read the manual on what to do on full file systems.\n");
  949. X    cleanup(0);
  950. X}
  951. X
  952. X/*
  953. X * copy temp or whatever back to mailfile
  954. X * Return 0 if new mail came and user doesn't want to exit.
  955. X */
  956. Xcopyback()
  957. X{
  958. X    register int    new = 0, i, j=0, k=0;
  959. X    register long     flg = 0;
  960. X    register FILE     *mbox = NULL_FILE, *mail_fp;
  961. X    char         *mbox_file, action = 0;
  962. X    int         hold = 0, delete_it = 0, dont_unlink = FALSE;
  963. X
  964. X#ifdef SUNTOOL
  965. X    if (istool) {
  966. X    timerclear(&(mail_timer.it_interval));
  967. X    timerclear(&(mail_timer.it_value));
  968. X    }
  969. X#endif SUNTOOL
  970. X    if (ison(glob_flags, READ_ONLY)) {
  971. X    print("Can't update %s: read only\n", mailfile);
  972. X    return 1;
  973. X    }
  974. X    if (check_new_mail()) {
  975. X    new = 1;
  976. X    if (!istool) {
  977. X        char buf[256];
  978. X        if (iscurses)
  979. X        putchar('\n');
  980. X        print("Really quit? "), fflush(stdout);
  981. X        buf[0] = 0;
  982. X        if (!Getstr(buf, 256, 0) || lower(*buf) != 'y')
  983. X        return 0;
  984. X    }
  985. X    } else if (!msg_cnt) /* prevent unnecessary overwrite */
  986. X    return 0;
  987. X    /* open mbox if: "autodelete" AND "hold" are NOT set. */
  988. X    if (is_spool(mailfile)
  989. X        && !(delete_it = !!do_set(set_options, "autodelete"))
  990. X        && !(hold = !!do_set(set_options, "hold"))) {
  991. X    register char *p;
  992. X    int x = 1; /* tell getpath to ignore "ENOENT" if file not found */
  993. X
  994. X    if (!(p = do_set(set_options, "mbox")))
  995. X        p = DEF_MBOX;
  996. X    mbox_file = getpath(p, &x);
  997. X    if (x) {
  998. X        if (x > 0)
  999. X        print("%s is a directory.\n", mbox_file);
  1000. X        else
  1001. X        print("can't open %s: %s\n", p, mbox_file);
  1002. X        mbox = NULL_FILE;
  1003. X    } else {
  1004. X        char *mode = "a";
  1005. X        if (access(mbox_file, 0)) /* does it exist? */
  1006. X        mode = "w"; /* no, create it. */
  1007. X        else if (access(mbox_file, 2))   /* if yes, can we write in it? */
  1008. X        error("can't open %s", mbox_file); /* if no, print why not */
  1009. X        if (!(mbox = fopen(mbox_file, mode)))
  1010. X        error("can't open %s", mbox_file);
  1011. X    }
  1012. X    }
  1013. X    /* reopen the mailfile; make sure it's not readable */
  1014. X    {
  1015. X    int omask = umask(077);
  1016. X    mail_fp = fopen(mailfile, "w");
  1017. X    (void) umask(omask);
  1018. X    if (!mail_fp) {
  1019. X        error("can't rewrite %s", mailfile);
  1020. X        return 0;
  1021. X    }
  1022. X    }
  1023. X    turnon(glob_flags, IGN_SIGS);
  1024. X    print("Updating \"%s\"", mailfile), fflush(stdout);
  1025. X#ifdef SYSV
  1026. X    (void) locking(fileno(mail_fp), LK_LOCK,  0);
  1027. X#else
  1028. X#ifdef BSD
  1029. X    if (flock(fileno(mail_fp), LOCK_EX))
  1030. X    error("WARNING: could not lock %s", mailfile);
  1031. X#endif BSD
  1032. X#endif SYSV
  1033. X    turnon(flg, UPDATE_STATUS);
  1034. X    turnon(flg, NO_IGNORE);
  1035. X
  1036. X    for (i = 0; i < msg_cnt; i++)
  1037. X    /* check to see if message is marked for deletion or, if read and not
  1038. X     * preserved, delete it if autodelete is set. Otherwise, save the
  1039. X     * message in the spool file if hold is set. If all fails, save in mbox.
  1040. X     */
  1041. X    if (ison(msg[i].m_flags, DELETE)
  1042. X        || isoff(msg[i].m_flags, UNREAD) && isoff(msg[i].m_flags, PRESERVE) 
  1043. X        && delete_it) {
  1044. X        Debug("%s %d",
  1045. X        (action!='d')? "\ndeleting message:" : "", i+1), action = 'd';
  1046. X        continue;
  1047. X    } else if (ison(msg[i].m_flags, UNREAD) ||
  1048. X         ison(msg[i].m_flags, PRESERVE) || hold || !mbox) {
  1049. X        j++;
  1050. X        Debug("%s %d",
  1051. X        (action!='s')? "\nsaving in spool:" : "", i+1), action = 's';
  1052. X        if (copy_msg(i, mail_fp, flg) == -1) {
  1053. X        error("WARNING: could not write back to spool");
  1054. X        print("ALL mail left in %s\n", tempfile);
  1055. X        print("Spool mailbox may be corrupted.\n");
  1056. X        if (new)
  1057. X            print("New mail may be lost. :-(\n");
  1058. X        dont_unlink = TRUE;
  1059. X        break;
  1060. X        }
  1061. X    } else if (is_spool(mailfile)) {   /* copy back to mbox if spooldir */
  1062. X        k++;
  1063. X        if (copy_msg(i, mbox, flg) == -1) {
  1064. X        error("WARNING: could not write to mbox");
  1065. X        print("Unresolved mail left in %s\n", tempfile);
  1066. X        dont_unlink = TRUE;
  1067. X        break;
  1068. X        }
  1069. X        Debug("%s %d",
  1070. X        (action!='m')? "\nsaving in mbox:" : "", i+1), action = 'm';
  1071. X    }
  1072. X    Debug("\n%s", mailfile);
  1073. X#ifdef SYSV
  1074. X    locking(fileno(mail_fp), LK_UNLCK, 0);
  1075. X#endif SYSV
  1076. X    fclose(mail_fp);        /* implicit unlock for BSD */
  1077. X    if (mbox)
  1078. X    fclose(mbox);
  1079. X    if (j) {
  1080. X    long times[2];
  1081. X    times[1] = time(×[0]) - (long)2;
  1082. X    if (is_spool(mailfile) && utime(mailfile, times))
  1083. X        error("utime");
  1084. X    print_more(": saved %d message%s\n", j, (j==1)? NO_STRING: "s");
  1085. X    } else if (!is_spool(mailfile) && !dont_unlink && !new)
  1086. X    if (unlink(mailfile))
  1087. X        turnon(glob_flags, CONT_PRNT), error(": cannot remove");
  1088. X    else
  1089. X        print_more(": removed\n");
  1090. X    else
  1091. X    print_more(": empty\n");
  1092. X    if (k)
  1093. X    print("saved %d message%s in %s\n",k,(k==1)? NO_STRING: "s",mbox_file);
  1094. X    if (new && !istool)
  1095. X    print("New mail has arrived.\n");
  1096. X    turnoff(glob_flags, IGN_SIGS);
  1097. X#ifdef SUNTOOL
  1098. X    if (istool) {
  1099. X    mail_timer.it_value.tv_sec = time_out;
  1100. X    setitimer(ITIMER_REAL, &mail_timer, NULL);
  1101. X    }
  1102. X#endif SUNTOOL
  1103. X    return 1;
  1104. X}
  1105. X
  1106. Xmail_size()
  1107. X{
  1108. X    struct stat buf;
  1109. X    if (!is_spool(mailfile)) {
  1110. X    char tmp[128];
  1111. X    if (!stat(sprintf(tmp, "%s/%s", MAILDIR, login), &buf))
  1112. X        spool_size = buf.st_size;
  1113. X    }
  1114. X    if (!*mailfile)
  1115. X    return 0;
  1116. X    if (stat(mailfile, &buf)) {
  1117. X    if (errno != ENOENT)
  1118. X        error("Can't stat %s", mailfile);
  1119. X    return 0;
  1120. X    }
  1121. X    if (is_spool(mailfile))
  1122. X    spool_size = buf.st_size;
  1123. X    if (buf.st_size > last_size) {
  1124. X    last_size = buf.st_size;
  1125. X    return 1;
  1126. X    }
  1127. X    return 0;
  1128. X}
  1129. X
  1130. Xvoid
  1131. Xmail_status(as_prompt)
  1132. X{
  1133. X    static char buf[256];
  1134. X    register int cnt = 0, new = 0, unread = 0, deleted = 0;
  1135. X
  1136. X    for ( ; cnt < msg_cnt; cnt++) {
  1137. X    if (ison(msg[cnt].m_flags, UNREAD))
  1138. X        unread++;
  1139. X    if (ison(msg[cnt].m_flags, DELETE))
  1140. X        deleted++;
  1141. X    if (isoff(msg[cnt].m_flags, OLD))
  1142. X        new++;
  1143. X    }
  1144. X    if (as_prompt) {
  1145. X    register char *p, *b = buf;
  1146. X    for (p = prompt; *p; p++)
  1147. X        if (*p == '\\')
  1148. X        switch (*++p) {
  1149. X            case 'n': case 'r': *b++ = '\n';
  1150. X            when 't': *b++ = '\t';
  1151. X            otherwise: *b++ = *p;
  1152. X        }
  1153. X        else if (*p == '%')
  1154. X        switch (*++p) {
  1155. X            case 'm':
  1156. X            b += strlen(sprintf(b,"%d",(msg_cnt)? current_msg+1:0));
  1157. X            when 't':
  1158. X            b += strlen(sprintf(b, "%d", msg_cnt));
  1159. X            when 'd':
  1160. X            b += strlen(sprintf(b, "%d", deleted));
  1161. X            when 'u':
  1162. X            b += strlen(sprintf(b, "%d", unread));
  1163. X            when 'n':
  1164. X            b += strlen(sprintf(b, "%d", new));
  1165. X            when 'f':
  1166. X            b += Strcpy(b, mailfile);
  1167. X            if (ison(glob_flags, READ_ONLY))
  1168. X                b += Strcpy(b, " [read only]");
  1169. X            when 'T': case 'D': case 'Y': case 'M': case 'N':
  1170. X            b += Strcpy(b, Time(p, (long)0));
  1171. X            otherwise: *b++ = *p;
  1172. X        }
  1173. X        else if (*p == '!')
  1174. X        b += strlen(sprintf(b, "%d", hist_no+1));
  1175. X        else
  1176. X        *b++ = *p;
  1177. X    *b = 0;
  1178. X    print("%s", buf); /* buf MIGHT have a % in it... don't pass as fmt */
  1179. X    return;
  1180. X    }
  1181. X    (void) sprintf(buf,"\"%s\"%s: %d message%s, %d new, %d unread",
  1182. X    mailfile, ison(glob_flags, READ_ONLY)? " [read only]" : "",
  1183. X    msg_cnt, (msg_cnt != 1)? "s": NO_STRING, new, unread);
  1184. X    if (istool || iscurses)
  1185. X    (void) sprintf(buf+strlen(buf), ", %d deleted", deleted);
  1186. X#ifdef SUNTOOL
  1187. X    if (istool) {
  1188. X    static char ic_text[4];
  1189. X    extern struct pixrect mail_icon_image1, mail_icon_image2;
  1190. X    (void) sprintf(ic_text, "%3d", msg_cnt);
  1191. X    tool_set_attributes(tool,
  1192. X        WIN_LABEL, buf,
  1193. X        WIN_ICON_LABEL, ic_text,
  1194. X        WIN_ICON_IMAGE, ison(glob_flags, NEW_MAIL)?
  1195. X        &mail_icon_image2 : &mail_icon_image1,
  1196. X        0);
  1197. X    } else
  1198. X#endif SUNTOOL
  1199. X#ifdef CURSES
  1200. X    if (iscurses)
  1201. X        mvprintw(0, 0, "%-3d %-*s",
  1202. X        ((msg_cnt)? current_msg+1 : 0), COLS-5, buf), clrtoeol();
  1203. X    else
  1204. X#endif CURSES
  1205. X        puts(buf);
  1206. X    return;
  1207. X}
  1208. X
  1209. X/* return -1 since function doesn't affect messages */
  1210. Xcheck_flags(flags)
  1211. Xu_long flags;
  1212. X{
  1213. X    print_more(" ");
  1214. X    if (ison(flags, VERBOSE))
  1215. X    print_more("VERBOSE ");
  1216. X    if (ison(flags, INCLUDE))
  1217. X    print_more("INCLUDE ");
  1218. X    if (ison(flags, INCLUDE_H))
  1219. X    print_more("INCLUDE_H ");
  1220. X    if (ison(flags, EDIT))
  1221. X    print_more("EDIT ");
  1222. X    if (ison(flags, SIGN))
  1223. X    print_more("SIGN ");
  1224. X    if (ison(flags, DO_FORTUNE))
  1225. X    print_more("DO_FORTUNE ");
  1226. X    if (ison(flags, NO_HEADER))
  1227. X    print_more("NO_HEADER ");
  1228. X    if (ison(flags, DELETE))
  1229. X    print_more("DELETE ");
  1230. X    if (ison(flags, OLD))
  1231. X    print_more("OLD ");
  1232. X    if (ison(flags, UNREAD))
  1233. X    print_more("UNREAD ");
  1234. X    if (ison(flags, UPDATE_STATUS))
  1235. X    print_more("UPDATE_STATUS ");
  1236. X    if (ison(flags, NO_PAGE))
  1237. X    print_more("NO_PAGE ");
  1238. X    if (ison(flags, INDENT))
  1239. X    print_more("INDENT ");
  1240. X    if (ison(flags, NO_IGNORE))
  1241. X    print_more("NO_IGNORE ");
  1242. X    if (ison(flags, PRESERVE))
  1243. X    print_more("PRESERVE ");
  1244. X    print_more("\n");
  1245. X    return -1;
  1246. X}
  1247. END_OF_FILE
  1248. if test 16268 -ne `wc -c <'msgs.c'`; then
  1249.     echo shar: \"'msgs.c'\" unpacked with wrong size!
  1250. fi
  1251. # end of 'msgs.c'
  1252. fi
  1253. if test -f 'mush.h' -a "${1}" != "-c" ; then 
  1254.   echo shar: Will not clobber existing file \"'mush.h'\"
  1255. else
  1256. echo shar: Extracting \"'mush.h'\" \(17878 characters\)
  1257. sed "s/^X//" >'mush.h' <<'END_OF_FILE'
  1258. X/* @(#)mush.h    (c) copyright 1986 (Dan Heller) */
  1259. X
  1260. X#define VERSION "Mail User's Shell (Vers 5.7) Sun Sep  6 19:10:48 PDT 1987"
  1261. X
  1262. X#include "config.h"
  1263. X
  1264. X#ifdef CURSES
  1265. X#include <curses.h>
  1266. X#else CURSES
  1267. X#include <stdio.h>
  1268. X#endif /* CURSES */
  1269. X
  1270. X#include <ctype.h>
  1271. X#include <errno.h>
  1272. X#include <setjmp.h>
  1273. X#include "strings.h"
  1274. X
  1275. X#ifdef SUNTOOL
  1276. X#    include <suntool/tool_hs.h>
  1277. X#else  SUNTOOL
  1278. X#    include <sys/types.h>
  1279. X#    include <signal.h>
  1280. X#    ifndef SYSV
  1281. X#        include <sys/time.h>
  1282. X#     include <sys/ioctl.h>   /* for ltchars */
  1283. X#    else
  1284. X#        include <time.h>
  1285. X#        include <fcntl.h>
  1286. X#    endif /* SYSV */
  1287. X#endif /* SUNTOOL */
  1288. X
  1289. X#include <sys/stat.h>
  1290. X#include <sys/file.h>
  1291. X
  1292. X#ifdef SUNTOOL
  1293. X#    include <suntool/gfxsw.h>
  1294. X#    include <suntool/panel.h>
  1295. X#    include <suntool/ttysw.h>
  1296. X#    include <suntool/ttytlsw.h>
  1297. X#    include <suntool/menu.h>
  1298. X#    include <suntool/icon_load.h>
  1299. X#endif /* SUNTOOL */
  1300. X
  1301. X/* if no maximum number of files can be found, we'll use getdtablesize() */
  1302. X#ifdef _NFILE
  1303. X#    define MAXFILES _NFILE
  1304. X#else
  1305. X#ifdef NOFILE
  1306. X#    define MAXFILES NOFILE
  1307. X#endif
  1308. X#endif
  1309. X
  1310. X#ifndef CTRL
  1311. X#define CTRL(c)        ('c' & 037)
  1312. X#endif
  1313. X
  1314. X#define ESC         '\033'
  1315. X
  1316. X#define NO_STRING    ""
  1317. X#ifdef  NULL
  1318. X#undef  NULL
  1319. X#endif /*  NULL */
  1320. X#define NULL        (char *)0
  1321. X#define NULL_FILE    (FILE *)0
  1322. X#define DUBL_NULL    (char **)0
  1323. X#define TRPL_NULL    (char ***)0
  1324. X#ifdef putchar
  1325. X#undef putchar
  1326. X#endif /* putchar */
  1327. X#define putchar(c)    fputc(c, stdout)
  1328. X#define bell()         fputc('\007', stderr)
  1329. X
  1330. X#define on_intr() \
  1331. X    turnoff(glob_flags, WAS_INTR), oldint = signal(SIGINT, interrupt), \
  1332. X    oldquit = signal(SIGQUIT, interrupt)
  1333. X
  1334. X#define off_intr() \
  1335. X    turnoff(glob_flags, WAS_INTR), (void) signal(SIGINT, oldint), \
  1336. X    (void) signal(SIGQUIT, oldquit)
  1337. X
  1338. X/* Don't flush input when setting echo or cbreak modes (allow typeahead) */
  1339. X#ifdef TIOCSETN
  1340. X#define stty(fd, sgttybuf)    (ioctl(fd, TIOCSETN, sgttybuf))
  1341. X#endif /* TIOCSETN */
  1342. X
  1343. X#ifndef CURSES
  1344. X/* if curses is not defined, simulate the same tty based macros */
  1345. Xstruct sgttyb _tty;
  1346. X
  1347. X#define crmode()   (_tty.sg_flags |= CBREAK,  stty(0, &_tty))
  1348. X#define nocrmode() (_tty.sg_flags &= ~CBREAK, stty(0, &_tty))
  1349. X#define echo()     (_tty.sg_flags |= ECHO,    stty(0, &_tty))
  1350. X#define noecho()   (_tty.sg_flags &= ~ECHO,   stty(0, &_tty))
  1351. X#define savetty()  (void) gtty(0, &_tty)
  1352. X#endif /* ~CURSES */
  1353. X
  1354. X#define echo_on()    \
  1355. X    if (_tty.sg_flags && isoff(glob_flags, ECHO_FLAG)) echo(), nocrmode()
  1356. X#define echo_off()    \
  1357. X    if (_tty.sg_flags && isoff(glob_flags, ECHO_FLAG)) noecho(), crmode()
  1358. X
  1359. X#define strdup(dst, src) (xfree (dst), dst = savestr(src))
  1360. X#define Debug        if (debug) printf
  1361. X
  1362. X#ifdef SYSV
  1363. X#define L_SET    0
  1364. X#define F_OK    000
  1365. X#define R_OK    004
  1366. X#define W_OK    002
  1367. X#define E_OK    001
  1368. X#define u_long  ulong_t
  1369. X#define vfork   fork
  1370. X#define SIGCHLD SIGCLD
  1371. X#endif /*  SYSV */
  1372. X
  1373. X#if !defined(SUNTOOL) && !defined(CURSES)
  1374. X
  1375. X#define TRUE          1
  1376. X#define FALSE          0
  1377. X#define print          printf
  1378. X#define wprint          printf
  1379. X#define print_more      printf
  1380. X
  1381. X#endif /* SUNTOOL && !CURSES */
  1382. X
  1383. X#ifndef max
  1384. X#define max(a,b) (((a) > (b)) ? (a) : (b))
  1385. X#define min(a,b) (((a) < (b)) ? (a) : (b))
  1386. X#endif /*  max */
  1387. X
  1388. X#if defined(CURSES) && !defined(SUNTOOL)
  1389. X#define wprint printf
  1390. X#endif /* !SUNTOOL && CURSES */
  1391. X
  1392. X#if defined(CURSES) || defined(SUNTOOL)
  1393. X#define print_more      turnon(glob_flags, CONT_PRNT), print
  1394. Xvoid print();        /* printf to window or curses or tty accordingly */
  1395. X#endif /* CURSES || SUNTOOL */
  1396. X
  1397. X#ifdef  SUNTOOL
  1398. X
  1399. X#define NO_ITEM          (Panel_item)0
  1400. X#define NO_EVENT      (struct inputevent *)0
  1401. X#define TIME_OUT      60           /* sleep 60 secs between mailchecks */
  1402. X#define PIX_OR          PIX_SRC ^ PIX_DST
  1403. X#define ID           event.ie_code
  1404. X#define l_width(font)      fonts[font]->pf_defaultsize.x /* width of letter */
  1405. X#define l_height(font)      fonts[font]->pf_defaultsize.y /* height of letter */
  1406. X#define Clrtoeol(w,x,y,f) pw_text(w, x, y, PIX_SRC, fonts[f], blank)
  1407. X
  1408. X#define highlight(win,x,y,font,s) \
  1409. X    pw_text(win,x,y, PIX_SRC, fonts[font],s), \
  1410. X    pw_text(win,x+1,y, \
  1411. X    (ison(glob_flags, REV_VIDEO))? PIX_NOT(PIX_SRC): PIX_SRC|PIX_DST, \
  1412. X    fonts[font],s)
  1413. X
  1414. X/* Fonts */
  1415. X#define FONTDIR          "/usr/lib/fonts/fixedwidthfonts"
  1416. X#define DEFAULT          0
  1417. X#define SMALL           1
  1418. X#define LARGE           2
  1419. X#define MAX_FONTS      3
  1420. X
  1421. X#endif /* SUNTOOL */
  1422. X
  1423. X/* bits and pieces */
  1424. X#define turnon(flg,val)   ((flg) |= ((u_long)1 << ((u_long)(val)-1L)))
  1425. X#define turnoff(flg,val)  ((flg) &= ~((u_long)1 << ((u_long)(val)-1L)))
  1426. X#define ison(flg,val)     ((u_long)(flg) & ((u_long)1 << ((u_long)(val)-1L)))
  1427. X#define isoff(flg,val)    (!ison((flg), (val)))
  1428. X#define set_isread(n)      \
  1429. X    if (ison(msg[n].m_flags, UNREAD)) \
  1430. X        turnon(glob_flags, DO_UPDATE), turnoff(msg[n].m_flags, UNREAD)
  1431. X
  1432. X/* msg lists represented by bits */
  1433. X#define clear_msg_list(list)      (void) bzero(list, (msg_cnt+7)/8)
  1434. X#define msg_bit(list, n)    ((list[(n) / 8] >> ((n) % 8)) & 1)
  1435. X#define set_msg_bit(list, n)    (list[(n) / 8] |= (1 << ((n) % 8)))
  1436. X#define unset_msg_bit(list, n)  (list[(n) / 8] &= ~(1 << ((n) % 8)))
  1437. X#define bput(S1, S2, Len, op)                   \
  1438. X        {                         \
  1439. X            register char *s1 = S1, *s2 = S2;         \
  1440. X            register int len = Len;             \
  1441. X            while(len--)                 \
  1442. X            *s2++ op *s1++;             \
  1443. X        }
  1444. X#define bitput(m1,m2,len,op)    bput(m1, m2, (((len)+7)/8), op)
  1445. X
  1446. X/* convenience and/or readability */
  1447. X#define when          break;case
  1448. X#define otherwise      break;default
  1449. X#define lower(c)      (isupper(c)? tolower(c): c)
  1450. X#define Lower(c)      (c = lower(c))
  1451. X#define upper(c)      (islower(c)? toupper(c): c)
  1452. X#define Upper(c)      (c = upper(c))
  1453. X#define skipspaces(n)     for(p += (n); *p == ' ' || *p == '\t'; ++p)
  1454. X#define skipdigits(n)     for(p += (n); isdigit(*p); ++p)
  1455. X
  1456. X#define NO_FLG        0
  1457. X
  1458. X/* various flags */
  1459. Xlong   glob_flags;    /* global boolean flags thruout the whole program */
  1460. X#define DO_UPDATE   1    /* check for changes to avoid unnecessary copyback */
  1461. X#define REV_VIDEO   2    /* reverse video for curses or toolmode */
  1462. X#define CONT_PRNT   3    /* continue to print (maybe a printf) without a '\n' */
  1463. X#define DO_SHELL    4    /* run a shell even if no mail? (true if tool) */
  1464. X#define DO_PIPE     5    /* true if commands are piping to another command */
  1465. X#define IS_PIPE     6    /* true if commands' "input" is piped from another */
  1466. X#define IGN_SIGS    7    /* true if catch() should not longjump */
  1467. X#define IGN_BANG    8    /* ignore ! as a history reference (see source()) */
  1468. X#define ECHO_FLAG   9    /* if true, echo|cbreak is ON, don't echo typing (-e) */
  1469. X#define IS_GETTING 10    /* true if we're getting input for a letter */
  1470. X#define PRE_CURSES 11    /* true if curses will be run, but hasn't started yet */
  1471. X#define READ_ONLY  12    /* -r passed to folder() (or main) setting read only */
  1472. X#define REDIRECT   13    /* true if stdin is being redirected */
  1473. X#define WAS_INTR   14    /* catch interrupts, set this flag (signals.c) */
  1474. X#define WARNING    15   /* if set, various warning messages may be printed */
  1475. X#define NEW_MAIL   17   /* new mail has arrived; user is busy or in icon mode */
  1476. X
  1477. X#define VERBOSE        1       /* verbose flag for sendmail */
  1478. X#define INCLUDE        2       /* include msg in response */
  1479. X#define INCLUDE_H    3    /* include msg with header */
  1480. X#define EDIT        4    /* enter editor by defualt on mailing */
  1481. X#define SIGN        5    /* auto-include ~/.signature in mail */
  1482. X#define DO_FORTUNE    6    /* add a fortune at end of msgs */
  1483. X
  1484. X/* msg flags */
  1485. X#define NO_HEADER    7    /* don't print header of message (top, write) */
  1486. X#define DELETE        8
  1487. X#define OLD            9
  1488. X#define UNREAD        10
  1489. X#define UPDATE_STATUS    11    /* change status of msg when copyback */
  1490. X#define NO_PAGE        12    /* don't page this message */
  1491. X#define INDENT        13    /* indent included msg with string */
  1492. X#define NO_IGNORE    14    /* don't ignore headers */
  1493. X#define PRESERVE    15      /* preserve in mailbox unless deleted */
  1494. X#define TOP        15    /* just print the top of the message */
  1495. X#define FORWARD        16    /* Forward messages into the message buffer */
  1496. X
  1497. X#define    MAXMSGS_BITS    MAXMSGS/sizeof(char)    /* number of bits for bitmap */
  1498. X
  1499. Xstruct msg {
  1500. X    u_long m_flags;
  1501. X    long   m_offset;               /* offset in tempfile of msg */
  1502. X    long   m_size;                 /* number of bytes in msg */
  1503. X    int    m_lines;                /* number of lines in msg */
  1504. X} msg[MAXMSGS];
  1505. X
  1506. Xstruct options {
  1507. X    char *option;
  1508. X    char *value;
  1509. X    struct options *next;
  1510. X} *set_options, *aliases, *ignore_hdr, *functions, *fkeys, *own_hdrs;
  1511. X#ifdef CURSES
  1512. Xstruct options *bindings;
  1513. X#endif /* CURSES */
  1514. X
  1515. Xstruct cmd {
  1516. X    char *command;
  1517. X    int (*func)();
  1518. X};
  1519. Xextern struct cmd ucb_cmds[];
  1520. Xextern struct cmd cmds[], hidden_cmds[];
  1521. X#ifdef SUNTOOL
  1522. Xextern struct cmd fkey_cmds[];
  1523. X#endif /* SUNTOOL */
  1524. X
  1525. XFILE
  1526. X    *tmpf,        /* temporary holding place for all mail */
  1527. X    *open_file(),    /* open a file or program for write/append */
  1528. X    *popen();        /* this should be in stdio.h */
  1529. X
  1530. Xextern char
  1531. X    *sys_errlist[],    /* system's list of global error messages */
  1532. X#ifdef SUNTOOL
  1533. X    *font_files[],     /* the names of the files fonts are kept in */
  1534. X    *alt_fonts[],     /* fonts to use if first ones don't work */
  1535. X#endif /* SUNTOOL */
  1536. X    **environ;        /* user's environment variables */
  1537. X
  1538. Xextern int errno;    /* global system error number */
  1539. Xjmp_buf jmpbuf;        /* longjmp to jmpbuf on sigs (not in tool) */
  1540. X
  1541. Xchar
  1542. X    debug,        /* debug causes various print statements in code */
  1543. X    tempfile[40],    /* path to filename of temporary file */
  1544. X    msg_list[MAXMSGS_BITS],    /* MAXMSGS bits of boolean storage */
  1545. X    *cmd_help,        /* filename of location for "command -?" commands. */
  1546. X    *login,        /* login name of user */
  1547. X    *mailfile,        /* path to filename of current mailfile */
  1548. X    *ourname[MAX_HOST_NAMES],    /* the name and aliases of the current host */
  1549. X    *prompt,        /* the prompt string -- may have %d */
  1550. X    *escape,        /* the escape character when without editor */
  1551. X    *editor,         /* string describing editor to use (default vi) */
  1552. X    *hdrs_only,        /* true if -H flag was given --set to args */
  1553. X    *hdr_format,    /* set to the header format string; referenced a lot */
  1554. X    *visual,         /* string describing visual editor to use */
  1555. X    *pager,         /* string describing pager to use (default more) */
  1556. X    *argv_to_string(),    /* convert a vector of strings into one string */
  1557. X    **make_command(),    /* build a command vector (argv) */
  1558. X    **mk_argv(),    /* given a string, make a vector */
  1559. X    *itoa(),        /* return a string representation of a number */
  1560. X    *lcase_strcpy(),    /* just like strcpy, but convert all chars to lower */
  1561. X    *variable_stuff(),    /* return information about variables */
  1562. X    *no_newln(),    /* remove newline and extra whitespace - return end */
  1563. X    *savestr(),        /* strcpy arg into malloc-ed memory; return address */
  1564. X    *date_to_string(),    /* returns a string described by parse_date() */
  1565. X    *msg_date(),    /* return a string of the date of a message */
  1566. X    *parse_date(),    /* parse an ascii date, and return message-id str */
  1567. X    *Time(),        /* returns string expression of time (takes args) */
  1568. X    *do_range(),    /* parse a string converting to a "range" of numbers */
  1569. X    *getpath(),        /* static char returning path (expanding ~, +, %, #) */
  1570. X    *compose_hdr(),    /* returns a formatted line describing passed msg # */
  1571. X    *my_atoi(),     /* do an atoi, but return the last char parsed */
  1572. X    *do_set(),        /* set/unset an option, alias, ignored-hdr */
  1573. X    *reply_to(),    /* who do we reply to when responding */
  1574. X    *cc_to(),         /* when responding, return str which is the cc-list */
  1575. X    *subject_to(),      /* when responding, return str which is the subject */
  1576. X    *header_field(),    /* the line in msg described by arg (message header) */
  1577. X    *alias_to_address(),/* convert a name[list] to "real" names */
  1578. X    *set_header(),     /* [interactive] proc to set/display to/subject/cc */
  1579. X    *getenv(), *prog_name;
  1580. X
  1581. Xint
  1582. X    last_msg_cnt,    /* when checking for new mail, save the last msg_cnt */
  1583. X    msg_cnt,        /* total number of messages */
  1584. X    crt,        /* min number of lines msg contains to invoke pager */
  1585. X    current_msg,    /* the current message we're dealing with */
  1586. X    exec_pid,        /* pid of a command that has been "exec"ed */
  1587. X    hist_no,        /* command's history number */
  1588. X    iscurses;        /* if we're running curses */
  1589. X    istool,        /* argv[0] == "xxxxtool", ranges from 0 to 2 */
  1590. X    n_array[128],    /* array of message numbers in the header window */
  1591. X    screen,        /* number of headers window can handle */
  1592. X
  1593. X    quit(), cleanup(), catch(), do_alias(), respond(), cd(), sh(), stop(),
  1594. X    folder(), save_msg(), delete(), do_mail(), lpr(), alts(), set(), do_hdrs(),
  1595. X    rm_edfile(), pick(), save_opts(), preserve(), sort(), readmsg(),
  1596. X    do_pick(), print_help(), folders(), question_mark(), do_from(), my_stty(),
  1597. X    do_version(), disp_hist(), source(), do_echo(), sigchldcatcher(), ls(),
  1598. X    nopenfiles(), Setenv(), Unsetenv(), Printenv(), bus_n_seg(), msg_flags(),
  1599. X    toggle_debug(), stop_start(), interrupt();
  1600. X
  1601. Xlong
  1602. X    still_more,        /* there is still more message to display */
  1603. X    spool_size,        /* size of sppol mail regardless of current folder */
  1604. X    last_size,        /* the lastsize of the mailfile since last check */
  1605. X    time();        /* satisfy lint */
  1606. X
  1607. Xvoid
  1608. X    xfree(), free_vec(), error(), getmail(), mail_status(),
  1609. X    file_to_fp(), init(), display_msg(), c_more();
  1610. X    /* printf(), fclose(), fflush(), fputs(), fputc() */
  1611. X#ifndef CURSES
  1612. Xstruct sgttyb _tty;            /* tty characteristics */
  1613. X#endif /* CURSES */
  1614. X#ifdef TIOCGLTC
  1615. Xstruct ltchars ltchars;            /* tty character settings */
  1616. X#endif /* TIOCGLTC */
  1617. X
  1618. X#ifdef CURSES
  1619. X
  1620. X#define STANDOUT(y,x,s) standout(), mvaddstr(y,x,s), standend()
  1621. X#define redraw()    clearok(curscr, TRUE), wrefresh(curscr)
  1622. X
  1623. Xint
  1624. X    curses_init(),    /* interpret commands via the curses interface */
  1625. X    bind_it();        /* bind chars or strings to functions */
  1626. X#endif /* CURSES */
  1627. X
  1628. X#ifdef SUNTOOL
  1629. Xvoid
  1630. X    lock_cursors(), unlock_cursors(), scroll_win(),
  1631. X    set_fkeys(), set_key(), toggle_opt(), help_opt();
  1632. X
  1633. Xchar
  1634. X    *rite(),        /* rite a char to msg_win: return string if c == '\n' */
  1635. X    *find_key(),    /* pass x,y coords to find which function key assoc. */
  1636. X    *key_set_to(),    /* pass fkey string, return string describing func */
  1637. X    *panel_get(),          /* returns what has been typed in a panel item */
  1638. X    *tool_help,        /* help for tool-related things (sometimes, overlap) */
  1639. X    blank[128];        /* use to clear to end of line */
  1640. X
  1641. Xint
  1642. X    time_out,        /* time out interval to wait for new mail */
  1643. X    rootfd,        /* the root window's fd */
  1644. X    parentfd,        /* the parent's window fd */
  1645. X    getting_opts,    /* true if getting/setting opts from msg_win */
  1646. X    curfont,        /* the current font to use for mail message window */
  1647. X    total_fonts,    /* total number of fonts available */
  1648. X    get_hdr_field,    /* bitmask of header fields to be gotten */
  1649. X
  1650. X    msg_io(), msgwin_handlesigwinch(), hdr_io(), hdrwin_handlesigwinch(),
  1651. X    sigchldcatcher(), sigtermcatcher(), sigwinchcatcher(), do_sort(),
  1652. X    do_compose(), do_edit(), read_mail(), delete_mail(), respond_mail(),
  1653. X    do_hdr(), display_hdrs(), print_sigwinch(), p_set_opts(),
  1654. X    tool_mgmt(), do_help(), text_done(), msg_num_done(), do_lpr(),
  1655. X    toolquit(), change_font(), do_clear(), do_update(),
  1656. X    file_dir(), do_file_dir(), do_send(), abort_mail(), check_new_mail(),
  1657. X    fkey_cmd(), fkey_settings();
  1658. X
  1659. Xstruct tchars  tchars;            /* more tty character settings */
  1660. X
  1661. Xstruct tool *tool;      /* main tool structure */
  1662. Xstruct toolsw
  1663. X    *panel_sw,        /* main panel subwindow */
  1664. X    *hdr_sw,         /* subwindow for message headers */
  1665. X    *hdr_panel_sw,    /* panel for headers */
  1666. X    *tty_sw,         /* subwindow which forks a shell (usually editor) */
  1667. X    *print_sw,         /* subwindow for print statements */
  1668. X    *msg_sw;         /* main subwindow to display messages and more */
  1669. X
  1670. Xstruct pixwin
  1671. X    *msg_win,        /* main pixwin for message display and more */
  1672. X    *hdr_win,        /* pixwin for message headers */
  1673. X    *print_win;        /* pixwin for printing messages ( print() ) */
  1674. X
  1675. Xstruct pr_pos txt;               /* current position of text written */
  1676. Xstruct rect msg_rect, hdr_rect;         /* sizes of the main and hdr rects */
  1677. Xstruct pixfont *fonts[MAX_FONTS];    /* array of fonts */
  1678. X
  1679. XPanel
  1680. X    main_panel,        /* the main panel dealing with generic items */
  1681. X    hdr_panel;        /* panel which contains message header specific items */
  1682. X
  1683. XPanel_item
  1684. X    abort_item,        /* abort mail in progress */
  1685. X    alias_item,        /* set/view/change current mail aliases */
  1686. X    cd_item,        /* changes file_item to cd (for cd-ing) */
  1687. X    comp_item,        /* compose a letter */
  1688. X    delete_item,    /* delete/undelete messages */
  1689. X    edit_item,        /* edit a message */
  1690. X    font_item,        /* choose which font to use */
  1691. X    folder_item,    /* change folders */
  1692. X    file_item,         /* text item for files or directories (forlder/cd) */
  1693. X    hdr_display,    /* format message headers are displayed */
  1694. X    help_item,        /* choose this to get various help */
  1695. X    ignore_item,    /* set/view/change message headers to be ignored */
  1696. X    input_item,        /* text item to get values for set/unsetting values */
  1697. X    msg_num_item,    /* text item to explicity state which message to read */
  1698. X    next_scr,        /* display the next screenful of message headers */
  1699. X    option_item,    /* set/view/unset mail options */
  1700. X    prev_scr,        /* display the previous screen of messages */
  1701. X    print_item,        /* send current message to the printer */
  1702. X    quit_item,        /* quit tool/close to icon */
  1703. X    read_item,        /* read the current message */
  1704. X    respond_item,    /* respond to messages */
  1705. X    save_item,        /* saves messages; uses text item input_item */
  1706. X    send_item,        /* when composing letter, this will send it off */
  1707. X    sort_item,        /* sort routine... */
  1708. X    sub_hdr_item[6],    /* display items that just sit there and give help */
  1709. X    update_item;    /* commit changes to folder */
  1710. X
  1711. Xstruct itimerval mail_timer;    /* frequency to check for new mail */
  1712. X
  1713. X            /* mouse symbols and data */
  1714. X/* left, middle and right mouse pixrects */
  1715. Xstruct cursor
  1716. X    l_cursor, m_cursor, r_cursor, coffee, read_cursor, write_cursor,
  1717. X    main_cursor, checkmark;
  1718. X
  1719. Xstruct pixrect *msg_pix; /* pixrect holding text of a message */
  1720. Xextern struct pixrect mouse_left, mouse_middle, mouse_right;
  1721. Xextern struct pixrect dn_arrow, up_arrow, cycle, shade_50;
  1722. X
  1723. Xextern struct icon mail_icon;
  1724. X#endif /* SUNTOOL */
  1725. END_OF_FILE
  1726. if test 17878 -ne `wc -c <'mush.h'`; then
  1727.     echo shar: \"'mush.h'\" unpacked with wrong size!
  1728. fi
  1729. # end of 'mush.h'
  1730. fi
  1731. echo shar: End of archive 6 \(of 12\).
  1732. cp /dev/null ark6isdone
  1733. MISSING=""
  1734. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  1735.     if test ! -f ark${I}isdone ; then
  1736.     MISSING="${MISSING} ${I}"
  1737.     fi
  1738. done
  1739. if test "${MISSING}" = "" ; then
  1740.     echo You have unpacked all 12 archives.
  1741.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1742. else
  1743.     echo You still need to unpack the following archives:
  1744.     echo "        " ${MISSING}
  1745. fi
  1746. ##  End of shell archive.
  1747. exit 0
  1748.